package com.zmc.order.infrastructure.updater.order;

import com.zmc.common.domain.resp.order.ThirdPayResp;
import com.zmc.common.domain.vo.coupon.CouponSkuVo;
import com.zmc.common.domain.vo.coupon.CouponUpdateVo;
import com.zmc.common.domain.vo.good.GoodsUpVo;
import com.zmc.common.exception.base.BusinessException;
import com.zmc.common.utils.uuid.SnowflakeIdUtils;
import com.zmc.order.feign.CouponFeignService;
import com.zmc.order.feign.ProductFeignService;
import com.zmc.order.infrastructure.entity.MerchantOrderEntity;
import com.zmc.order.infrastructure.entity.OrderEntity;
import com.zmc.order.infrastructure.entity.OrderItemEntity;
import com.zmc.order.infrastructure.enums.OrderEnum;
import com.zmc.order.infrastructure.service.MerchantOrderService;
import com.zmc.order.infrastructure.service.OrderItemService;
import com.zmc.order.infrastructure.service.OrderService;
import org.apache.shardingsphere.transaction.annotation.ShardingSphereTransactionType;
import org.apache.shardingsphere.transaction.core.TransactionType;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @Author：zmc
 * @Date：2025/5/15 15:59
 * 分单
 */

@Component
public class OrderSplitUpdater<T> implements OderUpdater<T>{

    public static Logger log = LoggerFactory.getLogger(OrderSplitUpdater.class);

    @Autowired
    private OrderService orderService;

    @Autowired
    private MerchantOrderService merchantOrderService;

    @Autowired
    private OrderItemService orderItemService;

    @Autowired
    private ProductFeignService productFeignService;

    @Autowired
    private CouponFeignService couponFeignService;

    @Override
    @Transactional
    @ShardingSphereTransactionType(TransactionType.BASE)
    public void execute(T param) {
        ThirdPayResp payResp = (ThirdPayResp) param;
        String orderSn = payResp.getOrderSn();
        OrderEntity splitOrder = orderService.getByOrderSn(orderSn);
        if (splitOrder == null) {
            log.error("分单异常，找不到对应订单号, orderSn:{}", orderSn);
            throw new BusinessException("分单异常，找不到对应订单号");
        }
        if (splitOrder.getStatus() != OrderEnum.ORDER_STATUS_WAIT_FOR_PAY.getCode()) {
            log.error("分单异常，订单状态异常, orderSn:{}", orderSn);
            throw new BusinessException("分单异常，订单状态异常");
        }
        List<OrderItemEntity> itemList = orderItemService.listByOrderSn(splitOrder.getOrderSn());
        Map<String, List<OrderItemEntity>> listMap = itemList.stream().collect(Collectors.groupingBy(OrderItemEntity::getSpuId));
        //根据spu进行拆单
        List<OrderEntity> orderList = new ArrayList<>();
        List<MerchantOrderEntity> merchantOrderList = new LinkedList<>();
        for (Map.Entry<String, List<OrderItemEntity>> spuEntry : listMap.entrySet()) {
            List<OrderItemEntity> orderItemList = spuEntry.getValue();
            //构建订单信息
            OrderEntity order = constructOrder(payResp, splitOrder, orderItemList);
            orderItemList.forEach(item -> {
                item.setOrderSn(order.getOrderSn());
            });
            //构建商户订单信息
            MerchantOrderEntity merchantOrder = createMerchantOrder(order, orderItemList);
            order.setMerchantOrderSn(merchantOrder.getOrderSn());
            merchantOrder.setUserOrderSn(order.getOrderSn());
            orderList.add(order);
            merchantOrderList.add(merchantOrder);
        }
        //更新总订单
        orderService.updateStatusAndPayType(orderSn, OrderEnum.ORDER_STATUS_TOTAL_FINISH.getCode(), payResp.getType());
        //构建用户订单
        orderService.saveBatch(orderList);
        //构建商户订单
        merchantOrderService.saveBatch(merchantOrderList);
        //批量更新订单条目
        orderItemService.updateBatchByOrderAndSpu(orderSn, itemList);
        //更新库存
        List<GoodsUpVo> inventoryList = itemList.stream().map(item -> {
            GoodsUpVo goodsUpVo = new GoodsUpVo();
            goodsUpVo.setCount(item.getSkuQuantity());
            goodsUpVo.setSkuId(item.getSkuId());
            return goodsUpVo;
        }).collect(Collectors.toList());
        productFeignService.reduceStock(inventoryList).valid();
        //组装优惠卷数据
        List<CouponSkuVo> couponList = new ArrayList<>();
        itemList.stream().filter(item -> item.getCouponId() != null).forEach(item -> {
            CouponSkuVo vo = new CouponSkuVo();
            vo.setOrderSn(item.getOrderSn());
            vo.setSkuId(item.getSkuId());
            vo.setCouponId(item.getCouponId());
            couponList.add(vo);
        });
        //更新优惠卷信息
        if (!CollectionUtils.isEmpty(couponList)) {
            CouponUpdateVo vo = new CouponUpdateVo();
            vo.setOrderSn(orderSn);
            vo.setList(couponList);
            couponFeignService.updateCouponHistory(vo).valid();
        }

    }

    /**
     * 构建订单信息
     * */
    public OrderEntity constructOrder(ThirdPayResp payResp, OrderEntity splitOrder, List<OrderItemEntity> orderItemList) {
        //构建订单
        OrderEntity order = new OrderEntity();
        order.setOrderSn(SnowflakeIdUtils.nextSnowFlackId(payResp.getOrderSn()));
        order.setMemberId(splitOrder.getMemberId());
        order.setTradeSn(payResp.getTradeSn());
        order.setPaymentTime(LocalDateTime.now());
        order.setPayType(payResp.getType());
        order.setPaymentTime(splitOrder.getPaymentTime());
        order.setReceiverAddressId(splitOrder.getReceiverAddressId());
        order.setMemberUsername(splitOrder.getMemberUsername());
        order.setSourceType(OrderEnum.ORDER_SOURCE_PC.getCode());
        order.setStatus(OrderEnum.ORDER_STATUS_WAIT_SEND_GOOD.getCode());
        //运费
        order.setFreightAmount(BigDecimal.ZERO);
        //默认七天
        order.setAutoConfirmDay(7);
        //计算订单总金额
        BigDecimal totalPrice = orderItemList.stream().map(item -> {
            return item.getSkuPrice().multiply(new BigDecimal(item.getSkuQuantity()));
        }).reduce(BigDecimal::add).orElse(BigDecimal.ZERO);
        //实际支付金额
        BigDecimal realPrice = orderItemList.stream().map(OrderItemEntity::getRealAmount).reduce(BigDecimal::add).orElse(BigDecimal.ZERO);
        //促销优化金额（促销价、满减、阶梯价）
        order.setPromotionAmount(orderItemList.stream().map(OrderItemEntity::getPromotionAmount).reduce(BigDecimal::add).orElse(BigDecimal.ZERO));
        //积分抵扣金额
        order.setIntegrationAmount(orderItemList.stream().map(OrderItemEntity::getIntegrationAmount).reduce(BigDecimal::add).orElse(BigDecimal.ZERO));
        //优惠券抵扣金额
        order.setCouponAmount(orderItemList.stream().map(OrderItemEntity::getCouponAmount).reduce(BigDecimal::add).orElse(BigDecimal.ZERO));
        //可获得的积分、成长值
        order.setIntegration(orderItemList.stream().map(OrderItemEntity::getGiftIntegration).reduce(0, Integer::sum));
        order.setGrowth(orderItemList.stream().map(OrderItemEntity::getGiftGrowth).reduce(0, Integer::sum));
        //发票
        order.setBillType(0);
        //确认收货状态
        order.setConfirmStatus(0);
        order.setUseIntegration(0);
        order.setTotalAmount(totalPrice);
        order.setPayAmount(realPrice);
        order.setItems(orderItemList);
        return order;
    }

    /**
     * 创建商户订信息
     * */
    public MerchantOrderEntity createMerchantOrder(OrderEntity order, List<OrderItemEntity> orderItemList) {
        MerchantOrderEntity merchantOrder = new MerchantOrderEntity();
        String merchantId = orderItemList.get(0).getMerchantId();
        merchantOrder.setMerchantId(merchantId);
        merchantOrder.setOrderSn(SnowflakeIdUtils.nextSnowFlackId(merchantId));
        merchantOrder.setMemberUsername(order.getMemberUsername());
        merchantOrder.setTotalAmount(order.getTotalAmount());
        merchantOrder.setPayAmount(order.getPayAmount());
        merchantOrder.setFreightAmount(order.getFreightAmount());
        merchantOrder.setPromotionAmount(order.getPromotionAmount());
        merchantOrder.setIntegrationAmount(order.getIntegrationAmount());
        merchantOrder.setCouponAmount(order.getCouponAmount());
        merchantOrder.setDiscountAmount(order.getDiscountAmount());
        merchantOrder.setStatus(order.getStatus());
        merchantOrder.setPaymentTime(order.getPaymentTime());
        merchantOrder.setUserOrderSn(order.getOrderSn());
        return merchantOrder;
    }
}
